package GUI;

import parser.*;
import process.Process;
import process.DecisionMaker;
import java.io.*;
import java.util.Vector;

public class Tank implements Process {
	Vector U = new Vector();	/* <universe list> */
	Vector V = new Vector();	/* <variable list> */
	Vector R = new Vector();		/* <rule list> */

	private int level, outflux, influx;
	private double[] fuzzy_level, fuzzy_outflux;
	private double fuzzy_influx;

	/* constructor */
	public Tank()
	{
		fuzzy_level = new double[3];
		fuzzy_outflux = new double[3];

		// Select KB
    	String filename = "kb_tank.txt";

		// Parse KB into vectors
		Parse( filename );

		// Store level height and outflux values shown in GUI in local parameters
		setLevel();
		setOutflux();

		// Fuzzyfication	- Fuzzyficate values (create fuzzy values)
		setFuzzyLevel();
		setFuzzyOutflux();
		
		// DecisionMaker	- Determine influx (fuzzy)value with fuzzy values and rules (via vectors)
		setInflux( fuzzy_level, fuzzy_outflux );
		
		// Defuzzyficator	- Defuzzyficate influx fuzzy-value into real value (influx value)
	}

	/**
	 * Parse Knowledge Base into Vectors
	 */
	public void Parse( String filename )
	{
		kb_parser Parser = new kb_parser();

    	try { Parser.Parse( filename ); }
    	catch(IOException err) { System.out.println("Error; " + err); }

    	U = Parser.getUniverseVector();
    	V = Parser.getVariableVector();
    	R = Parser.getRuleVector();
	}

	/**
	 * Set local INTEGER level parameter
	 */
	public void setLevel()
	{
		// Get value from GUI
		// Put in local variable <level>
	}

	/**
	 * Set local INTEGER outflux parameter
	 */
	public void setOutflux()
	{
		// Get value from GUI
		// Put in local variable <outflux>
	}

	/**
	 * Set local DOUBLE (i.e. FUZZY) level parameter
	 */
	public void setFuzzyLevel()
	{
		// Give Fuzzyficator <level> value (integer)
		// Receive <fuzzy_level> value [0~1]
		
		fuzzy_level[0] = 0; // Sample !
		fuzzy_level[1] = 0;
		fuzzy_level[2] = 0.5;
	}

	/**
	 * Set local DOUBLE (i.e. FUZZY) outflux parameter
	 */
	public void setFuzzyOutflux()
	{
		// Give Fuzzyficator <outflux> value (integer)
		// Receive <outflux_level> value [0~1]

		fuzzy_outflux[0] = 0; // Sample !
		fuzzy_outflux[1] = 0.1;
		fuzzy_outflux[2] = 0.53;
	}

	public void setInflux( double[] fuzzyLevel, double[] fuzzyOutflux )
	{
		// Determine influx in Decisionmaker by providing fuzzy level and outflux values

		DecisionMaker DM = new DecisionMaker( fuzzy_level, fuzzy_outflux, R );

		fuzzy_influx = DM.getInflux();
	}
	
	/*	The method <getVariable> is used to get a variable <name> of the process. As a rule, an
	 *	input variable with the same name is declared in the Knowledge Base.
	 */
	public double getVariable(String name)
	{
		for(int i = 0; i < V.size(); i++)
		{
			if( (((Variable)V.elementAt(i)).getVarName()).equals(name) )
			{
				System.out.println("VARIABLE FOUND: " + name);
				// return a double???????
			} else
			{
				System.out.println("VARIABLE NOT FOUND: " + name);
			}
		}
		return -1;
	}
	
	/*	The method <setVariable> is used to assign a value <value> to a variable <name> of the
	 *	process. As a rule, an output variable with the same name is declared in the Knowledge
	 *	Base.
	 */
	public void setVariable(String name, double value)
	{
		if(name.equals("height") || name.equals("inFlux"))
		{
			for(int i = 0; i < V.size(); i++)
			{
				if(name.equals( ( (Variable)V.elementAt(i) ).getVarName() ) )
				{
					if(value == 1) /** value 1 corresponds with "in" */
					( (Variable)V.elementAt(i) ).setVarType("in");
					else if(value == 2) /** value 2 corresponds with "out" */
					( (Variable)V.elementAt(i) ).setVarType("out");
					else System.out.println("Error: value " + value + " is an unvalid value");
				}
			}
		} else System.out.println("Error: variable " + name + " does not exist.");
	}
	
	/* The method <simulateStep> is used to simulate the process during a time interval <deltaT>.
	 *	The FLC does not act during this time interval; afterwards, new sensor values can be read
	 *	and actuator values can be input (with <getVariable> and <setVariable> respectively).
	 *	Next, a new time interval is simulated by calling <simulateStep>, etc.
	 */
	public void simulateStep(double deltaT)
	{
	}
}
